﻿using UnityEngine;
using System.Collections.Generic;
using System;


namespace Framework.AssetsManager
{

    public class ResManager:Singleton<ResManager>
    {
        private Dictionary<string, EResType> m_allTypes = new Dictionary<string, EResType>();
        private Dictionary<EResType, Dictionary<string, UnityEngine.Object>> m_allDatas = new Dictionary<EResType, Dictionary<string, UnityEngine.Object>>();

        public ResManager()
        {
            Array res = Enum.GetValues(typeof(EResType));

           for (int i =0; i< res.Length;++i)
            {
                m_allDatas.Add((EResType)res.GetValue(i), new Dictionary<string, UnityEngine.Object>());
            }
        }

        public void AddResource(string _name, EResType _type, UnityEngine.Object _obj)
        {
            if (m_allTypes.ContainsKey(_name))
            {
                //Debug.LogWarning("Don`t add a existed resource:" + _name);
                return;
            }

            m_allTypes.Add(_name, _type);
            m_allDatas[_type].Add(_name, _obj);
        }

        public void RemoveResource(string _name)
        {
            EResType type;
            if (!m_allTypes.TryGetValue(_name, out type))
                return;

            RemoveResource(_name,type);
        }

        private void RemoveResource(string _name, EResType _type)
        {
            m_allTypes.Remove(_name);

            UnityEngine.Object obj;
            if (!m_allDatas[_type].TryGetValue(_name, out obj))
                return;

            m_allDatas[_type].Remove(_name);
        }

        public T GetResource<T>(string _name)  where T:UnityEngine.Object
        {
            return (T)GetResource(_name);
        }

        private T GetResource<T>(string _name, EResType _type)  where T: UnityEngine.Object
        {
            return (T)GetResource(_name, _type);
        }

        public UnityEngine.Object GetResource(string _name)
        {
            EResType type;
            if (!m_allTypes.TryGetValue(_name, out type))
                return null;

            return GetResource(_name, type);
        }

        private UnityEngine.Object GetResource(string _name, EResType _type)
        {
            UnityEngine.Object obj = null;
            m_allDatas[_type].TryGetValue(_name, out obj);
            return obj;
        }

        public bool isContains(string _name)
        {

            EResType type;
            if (!m_allTypes.TryGetValue(_name, out type))
                return false;

            return m_allDatas[type].ContainsKey(_name);
        }

        public void Clear(string _name)
        {
            EResType type;
            if (!m_allTypes.TryGetValue(_name, out type))
                return;

            m_allTypes.Remove(_name);

            UnityEngine.Object obj;
            if (!m_allDatas[type].TryGetValue(_name, out obj))
                return;

            if (obj as UnityEngine.Object != null)
            {
                if (type == EResType.ASSETBUNDLE)
                    (obj as AssetBundle).Unload(false);

                UnityEngine.Object.DestroyImmediate(obj as UnityEngine.Object);
            }

            m_allDatas[type].Remove(_name);
        }

        public void Clear()
        {
            Dictionary<EResType, Dictionary<string, UnityEngine.Object>>.Enumerator v = m_allDatas.GetEnumerator();

            while (v.MoveNext())
            {
                Dictionary<string, UnityEngine.Object> dict = v.Current.Value;

                Dictionary<string, UnityEngine.Object>.ValueCollection.Enumerator e = dict.Values.GetEnumerator();
                while (e.MoveNext())
                {
                    UnityEngine.Object obj = e.Current;

                    if (obj as UnityEngine.Object != null)
                    {
                        if (v.Current.Key == EResType.ASSETBUNDLE)
                            (obj as AssetBundle).Unload(false);

                        UnityEngine.Object.DestroyImmediate(obj as UnityEngine.Object);
                    }
                        
                    else
                        obj = null;
                }

                dict.Clear();
            }

            m_allTypes.Clear();

            Resources.UnloadUnusedAssets();
            System.GC.Collect();
        }

        public void Clear(EResType _type)
        {
            Dictionary<string, UnityEngine.Object> dict;

            if (!m_allDatas.TryGetValue(_type, out dict))
                return;

            Dictionary<string, UnityEngine.Object>.ValueCollection.Enumerator v = m_allDatas[_type].Values.GetEnumerator();
            Dictionary<string, UnityEngine.Object>.KeyCollection.Enumerator k = m_allDatas[_type].Keys.GetEnumerator();

            while (v.MoveNext())
            {
                UnityEngine.Object obj = v.Current;

                if ((obj as UnityEngine.Object) != null)
                {
                    if (_type == EResType.ASSETBUNDLE)
                        (obj as AssetBundle).Unload(false);
                    UnityEngine.Object.DestroyImmediate(obj as UnityEngine.Object);
                }
                else
                    obj = null;
            }

            while (k.MoveNext())
            {
                string key = k.Current;

                m_allTypes.Remove(key);
            }

            dict.Clear();

            Resources.UnloadUnusedAssets();

        }
    }
}